import { Container } from "../Container";
import { BaseGui } from "../Services/BaseGui";
import { HelperTool } from "../Services/Common";
import { ViewerService } from "../Services/ViewerService";
import { ModelSearchService } from "../Services/ModelSearchService";
import { DataService } from "../Services/DataService";

export class ModelSearchGui extends BaseGui {
    title = `模型搜索[${ModelSearchGui.name}]`;
    ViewerService = Container.defineProperty(ViewerService);
    DataService = Container.defineProperty(DataService);
    ModelSearchService = Container.defineProperty(ModelSearchService);
    private async searchModel(model: Sippreep.Viewing.Model, searchText: string) {
        return this.ViewerService.userFunction(model, (pdb, userData) => {
            let propFilters = new Array<string>();
            let filters = userData.split(";").map(item => {
                return item.split("&").map(_ => _.split("=")).map(_ => {
                    propFilters.push(_[0]);
                    return { Key: _[0], Value: _[1] };
                });
            });
            let eqult = (x: string, y: string) => {
                if (x == undefined)
                    return false;
                if (y.startsWith("!"))
                    return x.indexOf(y.slice(1)) < 0;
                return x.indexOf(y) >= 0;
            }
            let judge = (data: { [attrName: string]: string }, filter: { Key: string, Value: string }[]) => {
                for (let item of filter) {
                    if (!eqult(data[item.Key], item.Value))
                        return false;
                }
                return true;
            }

            let dbIds = new Array<number>();
            pdb.enumObjects((dbId: number) => {
                let objProp = pdb.getObjectProperties(dbId, propFilters);
                if (!objProp)
                    return;
                let objProp1: { [attrName: string]: string } = {};
                objProp.properties.forEach(_ => objProp1[_.attributeName] = _.displayValue);

                for (let filter of filters) {
                    if (judge(objProp1, filter)) {
                        dbIds.push(dbId);
                        break;
                    }
                }
            });
            return dbIds;
        }, searchText);
    }
    async UpdateGui() {
        await this.ViewerService.ViewerPromise;
        let array = this.ModelSearchService.getData();
        let fun = {
            add: () => {
                let name = "modelSearch" + (array.length + 1);
                array.push({ name: name, searchText: "" });
                fun.data = array.length - 1;
                fun._dataChange();
                updateGUI();
            },
            remove: () => {
                if (!window.confirm("确实要清除选中项吗？"))
                    return;
                array.splice(fun.data, 1);
                fun.data = fun.data < array.length ? fun.data : fun.data - 1;
                fun._dataChange();
                updateGUI();
            },
            clear: () => {
                if (array.length == 0)
                    return;
                if (!window.confirm("确实要清除所有？"))
                    return;
                array.splice(0, array.length);
                fun.data = -1;
                fun._dataChange();
                updateGUI();
            },
            data: -1,
            dataName: "",
            searchText: "",
            search: async () => {
                let resultPromses = this.ViewerService.viewer.getAllModels().map(async (m) => {
                    let dbIds = await this.searchModel(m, fun.searchText);
                    return { m, dbIds };
                });
                let results = await Promise.all(resultPromses);
                let sum = HelperTool.Sum(results, (item) => item.dbIds.length);
                alert(`搜索到${sum}个对象`);
                results.forEach(({ m, dbIds }) => {
                    m.selector.clearSelection();
                    m.selector.setSelection(dbIds, 0);
                });
            },
            help: () => {
                let message = `
                “;&=!”代表“或且等非”
                例如：
                1、“工作集=0”
                2、“工作集=0&分类=!墙”
                3、“工作集=0&分类=!墙;工作集=1&分类=墙”
                `;
                alert(message);
            },
            _dataOptions: () => {
                let options: { [name: string]: number } = {};
                this.ModelSearchService.getData().forEach((item, index) => {
                    options[`[${index + 1}]${item.name}`] = index;
                });
                return options;
            },
            _dataChange() {
                let data = array[fun.data];
                fun.dataName = data.name;
                fun.searchText = data.searchText;
                updateGUI();
            },
            _dataNameChanged: () => {
                let data = array[fun.data];
                data.name = fun.dataName;
                updateGUI();
            },
            _searchTextChanged: () => {
                let data = array[fun.data];
                if (data.searchText != fun.searchText) {
                    data.searchText = fun.searchText;
                    fun.search();
                }
            }
        }
        let gui = this.gui;
        let updateGUI = () => {
            Array.from(gui.__controllers).forEach(_ => {
                gui.remove(_);
            });
            this.guiService.buildGUIByObject(this.gui, fun);
        }
        updateGUI();

        return this;
    }
    Init(): void {
        this.DataService.OnDataChanged.addEventListener(() => {
            this.Refresh();
        })
    }
}
